/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2018-2024. All rights reserved.
 * Description: version definiation for aipp json parser.
 */
#include "aipp_json_parser.h"
#include <fstream>
#include <string>
#include <dirent.h>

#include "framework/infra/log/log.h"

using namespace std;
using json = nlohmann::json;
namespace hiai {
vector<string> Split(const string& inputStr, const string& delimiter)
{
    size_t pos = 0;
    string tok;
    string s = inputStr;
    vector<string> strList;
    while ((pos = s.find(delimiter)) != string::npos) {
        tok = s.substr(0, pos);
        if (!tok.empty()) {
            strList.push_back(tok);
        }
        s.erase(0, pos + delimiter.length());
    }
    if (!s.empty()) {
        strList.push_back(s);
    }
    return strList;
}

// trim from start (in place)
void LTrim(std::string& s)
{
    s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { return !std::isspace(ch); }));
}

// trim from end (in place)
void RTrim(std::string& s)
{
    s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(), s.end());
}

// trim from both ends (in place)
void Trim(std::string& s)
{
    LTrim(s);
    RTrim(s);
}

bool AippJsonParser::ReadFileToJson(const string& file, json& j)
{
    if (file.empty()) {
        FMK_LOGE("File is null.");
        return false;
    }

    char filePath[PATH_MAX + 1] = {0x00};
    if (realpath(file.c_str(), filePath) == nullptr) {
        FMK_LOGE("invalid path: %s.", file.c_str());
        return false;
    }

    ifstream fin(filePath, ios::in | ios::binary | ios::ate);
    bool result = false;
    char* buffer = nullptr;
    if (fin) {
        int64_t size = fin.tellg();
        if (size < 0) {
            FMK_LOGE("failed to tellg");
            fin.close();
            return false;
        }
        fin.seekg(0, ios::beg);
        buffer = new (std::nothrow) char[size]();
        if (buffer == nullptr) {
            FMK_LOGE("New buffer failed.");
            fin.close();
            return false;
        }
        fin.read(buffer, size);

        j = json::parse(buffer, buffer + size, nullptr, false);
        if (j.type() == json::value_t::discarded) {
            FMK_LOGE("Convert stream to json failed.");
        }
        result = true;
        fin.close();
        delete[] buffer;
        buffer = nullptr;
    } else {
        FMK_LOGE("Open %s failed.", filePath);
    }

    return result;
}

bool AippJsonParser::VarifyNodeInJson(const json& oriJson, const string& key)
{
    if (oriJson.find(key) != oriJson.end()) {
        return true;
    }

    return false;
}

bool AippJsonParser::GetNodeFromJson(const json& oriJson, const string& key, json& destJson)
{
    if (oriJson.find(key) != oriJson.end()) {
        destJson = oriJson[key];
        return true;
    }
    return false;
}

bool AippJsonParser::GetNodeListFromJson(const json& oriJson, const string& key, std::vector<json>& destJson)
{
    if (oriJson.find(key) != oriJson.end()) {
        json j = oriJson[key];
        for (json::iterator it = j.begin(); it != j.end(); it++) {
            json jNode = *it;
            destJson.push_back(jNode);
        }
        return true;
    }
    return false;
}

bool AippJsonParser::GetStringFromJson(const json& oriJson, const string& key, std::string& val)
{
    json data;
    if (!GetNodeFromJson(oriJson, key, data)) {
        return false;
    }
    if (!data.is_string()) {
        FMK_LOGE("Node %s 's string value type is invalid.", key.c_str());
        return false;
    }

    val = data.get<std::string>();
    return true;
}

bool AippJsonParser::GetIntFromJson(const json& oriJson, const string& key, int& val)
{
    json data;
    if (!GetNodeFromJson(oriJson, key, data)) {
        return false;
    }
    if (!data.is_number_integer()) {
        FMK_LOGE("Node %s 's integer value type is invalid.", key.c_str());
        return false;
    }

    val = data.get<int>();
    return true;
}

bool AippJsonParser::GetFloatFromJson(const json& oriJson, const string& key, float& val)
{
    json data;
    if (!GetNodeFromJson(oriJson, key, data)) {
        return false;
    }
    if (!data.is_number_float()) {
        FMK_LOGE("Node %s 's float value type is invalid.", key.c_str());
        return false;
    }

    val = data.get<float>();
    return true;
}

bool AippJsonParser::GetBoolFromJson(const json& oriJson, const string& key, bool& val)
{
    json data;
    if (!GetNodeFromJson(oriJson, key, data)) {
        return false;
    }
    if (!data.is_boolean()) {
        FMK_LOGE("Node %s 's bool value type is invalid.", key.c_str());
        return false;
    }

    val = data.get<bool>();
    return true;
}
}
